﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.IO;
using System.Drawing.Drawing2D;

namespace TextureConverter
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            fbDlg.SelectedPath = System.IO.Directory.GetCurrentDirectory();

            cmbOutputFormat.Items.Add(ImageFormat.Bmp);
            cmbOutputFormat.Items.Add(ImageFormat.Jpeg);
            cmbOutputFormat.Items.Add(ImageFormat.Png);
            cmbOutputFormat.Items.Add(ImageFormat.Tiff);
            cmbOutputFormat.Items.Add(ImageFormat.Gif);
            cmbOutputFormat.SelectedItem = ImageFormat.Png;
        }

        private void btnAddFiles_Click(object sender, EventArgs e)
        {
            if (ofDlgImages.ShowDialog() == DialogResult.OK)
            {
                lstFiles.Items.AddRange(ofDlgImages.FileNames);
            }
        }

        static int GetNextPowerOfTwo(int v)
        {
            // see http://en.wikipedia.org/wiki/Power_of_two
            v--;
            v |= v >> 1;
            v |= v >> 2;
            v |= v >> 4;
            v |= v >> 8;
            v |= v >> 16;
            v++;
            return v;
        }

        static int MostSignificantBit(int v)
        {
            if (v == 0)
                return -1;
            int b = 0;
            if (0 != (v >> 16)) { b += 16; v >>= 16; }
            if (0 != (v >> 8)) { b += 8; v >>= 8; }
            if (0 != (v >> 4)) { b += 4; v >>= 4; }
            if (0 != (v >> 2)) { b += 2; v >>= 2; }
            if (0 != (v >> 1)) { b += 1; }
            return b;
        }

        static int GetNearestPowerOfTwo(int v)
        {
            // see http://en.wikipedia.org/wiki/Power_of_two
            // 1. find most significant bit k
            int k = MostSignificantBit(v);
            // 2. check next lower bit
            if (k > 0)
            {
                if ((v & (1 << (k - 1))) != 0)
                    return (1 << (k + 1)); // go up
                else
                    return (1 << k);
            }
            else
                return 1;
        }

        private void btnConvert_Click(object sender, EventArgs e)
        {
            ImageFormat imgFmt = cmbOutputFormat.SelectedItem as ImageFormat;

            string fextToBe = "." + imgFmt.ToString().ToLower();
            if (fextToBe == ".jpeg")
                fextToBe = ".jpg";

            int maxRes = (int)nudMaxRes.Value;
            bool keepAspect = chkKeepAspect.Checked;

            foreach (string filename in lstFiles.Items)
            {
                using (Bitmap bmp = new Bitmap(filename))
                {
                    int width = bmp.Size.Width;
                    int height = bmp.Size.Height;

                    if (keepAspect)
                    {
                        float aspect = height / (float)width;
                        if (aspect < 1f) // width > height
                        {
                            width = Math.Min(width, maxRes);
                            height = (int)(aspect * width);
                        }
                        else // height > width
                        {
                            height = Math.Min(height, maxRes);
                            width = (int)(height / aspect);
                        }
                    }
                    else
                    {
                        width = Math.Min(width, maxRes);
                        height = Math.Min(height, maxRes);
                    }

                    if (chkNearestPow2.Checked)
                    {
                        width = GetNearestPowerOfTwo(width);
                        height = GetNearestPowerOfTwo(height);
                    }

                    if (chkMultipleOf4.Checked)
                    {
                        width = (width + 3) & ~3;
                        height = (height + 3) & ~3;
                    }

                    using (Bitmap dstBmp = new Bitmap(width, height, PixelFormat.Format32bppArgb))
                    {
                        using (Graphics g = Graphics.FromImage(dstBmp))
                        {
                            g.Clear(Color.Transparent);
                            g.InterpolationMode = InterpolationMode.Bicubic;
                            g.DrawImage(bmp, 0, 0, dstBmp.Width, dstBmp.Height);
                        }

                        string dstFilename = Path.GetFileNameWithoutExtension(filename) + fextToBe;
                        dstFilename = Path.Combine(txtOutputPath.Text, dstFilename);

                        dstBmp.Save(dstFilename, imgFmt);
                    }
                }
            }
        }

        private void btnBrowseOutputPath_Click(object sender, EventArgs e)
        {
            if (fbDlg.ShowDialog() == DialogResult.OK)
                txtOutputPath.Text = fbDlg.SelectedPath;
        }
    }
}
